简介 PyBind11 的主要目的是将已有的C++代码接口暴露给Python去调用。
使用者:
环境配置 macOS 1 2 3 #  python3.7 brew install python3 python3 -m pip install pybind11 
 
下载其他python版本:官方下载 
Ubuntu 
系统版本:18.04
 
1 sudo apt-get -y install python3 python3-dev python3-pip 
 
CentOS 
系统版本:7.5
 
 
Win 官方下载 
设置环境变量:
Q&A fatal error: ‘Python.h’ file not found 1 2 3 4 5 #  centos yum install python3-devel # 将会安装至 /usr/include #  ubuntu echo "export C_INCLUDE_PATH=${C_INCLUDE_PATH}:/usr/include/python3.6" >> ~/.bashrc echo "export CPLUS_INCLUDE_PATH=${CPLUS_INCLUDE_PATH}:/usr/include/python3.6" >> ~/.bashrc 
 
亦或是在 CMakeLists.txt 中包含
1 2 include_directories (SYSTEM /usr/include /python3.6 m)include_directories (SYSTEM /usr/local/include /python3.6 m)
 
ImportError: libSM.so.6: cannot open shared object file: No such file or directory 1 2 3 4 #  ubuntu apt-get install libsm6 libxrender1 libxext-dev #  centos yum install libXext libSM libXrender 
 
使用 前置 
工欲善其事,必先利其器。
 
将 C++  暴露给 Python  主要由两个方向:
将 函数 暴露给 Python 
将 类 暴露给 Python 
 
暴露函数 普通函数 C++示例源码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 #include  "pybind11/pybind11.h"  namespace  py = pybind11;int  add (int  l, int  r)   {    std ::cout  << "compute "  << l << " + "  << r << " :"  << std ::endl ;     return  l + r; } PYBIND11_MODULE(compute_pybind_state, m) { 		m.doc() = "pybind11 compute plugin" ;   	m.def("add" , &add, "a function which adds two numbers." , py::arg("l" ) = 1 , py::arg("r" ) = 2 ); } 
 
Python测试代码:
1 2 3 4 import  compute_pybind_state as  CXXprint(CXX.add(2 , 5 )) 
 
匿名函数 C++示例源码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 #include  "pybind11/pybind11.h"  namespace  py = pybind11;PYBIND11_MODULE(compute_pybind_state, m) { 		m.doc() = "pybind11 compute plugin" ;   	m.def(         "sub" ,         [](int  l, int  r) {             std ::cout  << "compute "  << l << " - "  << r << " :"  << std ::endl ;             return  l - r;         },         "a function which one sub another." , py::arg("l" ) = 2 , py::arg("r" ) = 1 ); } 
 
Python测试代码:
1 2 3 4 import  compute_pybind_state as  CXXprint(CXX.sub(3 , 1 )) 
 
模板函数 C++示例源码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 #include  "pybind11/pybind11.h"  namespace  py = pybind11;template  <typename  T>T square (T x)   { return  x * x; }PYBIND11_MODULE(compute_pybind_state, m) { 		m.doc() = "pybind11 compute plugin" ;   	m.def("square" , &square<double >);     m.def("square" , &square<float >);     m.def("square" , &square<int >); } 
 
Python测试代码:
1 2 3 4 5 import  compute_pybind_state as  CXXprint(CXX.square(2 )) print(CXX.square(2.2 )) 
 
重载函数 pybind11::overload_cast 只需要制定输入参数的类型,函数的返回值类型会自动推断 。
注意,该方法仅限于 C++14 及其以上版本方可支持。
C++示例源码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 #include  "pybind11/pybind11.h"  namespace  py = pybind11;int  sub (int  l, int  r)   {    std ::cout  << "compute int "  << l << " - "  << r << " :"  << std ::endl ;     return  l - r; } float  sub (float  l, float  r)   {    std ::cout  << "compute float "  << l << " - "  << r << " :"  << std ::endl ;     return  l - r; } PYBIND11_MODULE(compute_pybind_state, m) { 		m.doc() = "pybind11 compute plugin" ;   	m.def("sub" , py::overload_cast<int , int >(&sub), "a function which int numbers sub another." ,         py::arg("l" ) = 3 , py::arg("r" ) = 2 );     m.def("sub" , py::overload_cast<float , float >(&sub), "a function which float numbers sub another." ,         py::arg("l" ) = 3.0f , py::arg("r" ) = 2.0f ); } 
 
Python测试代码:
1 2 3 4 5 import  compute_pybind_state as  CXXprint(CXX.sub(3 , 2 )) print(CXX.sub(5.2 , 2.1 )) 
 
指针参数的函数 暴露类 C++示例源码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 class  Binary  {public :    Binary() = default ;     Binary(const  std ::string & type) : type_(type) {}     void  set (const  std ::string & type)   { type_ = type; }     void  set (const  int  v)   { std ::cout  << "overloaded function: "  << v << std ::endl ; }     const  std ::string  get ()   { return  type_ + "_mutable" ; }     const  std ::string  get ()  const   { return  type_ + "_const" ; }     float  compute (float  a, float  b)   {         std ::cout  << "compute "  << a << " "  << type_ << " "  << b << " :"  << std ::endl ;         if  (0  == type_.compare("add" )) return  a + b;         else  if  (0  == type_.compare("sub" )) return  a - b;         else  if  (0  == type_.compare("mul" )) return  a * b;         else  if  (0  == type_.compare("div" )) return  a / b;         else  std ::cout  << "unsupport type: "  << type_ << std ::endl ;         return  0.0f ;     }     std ::string  type_ = "add" ; }; 
 
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 #include  "pybind11/pybind11.h"  #include  "binary.h"  namespace  py = pybind11;int  sub (int  l, int  r)   {    std ::cout  << "compute int "  << l << " - "  << r << " :"  << std ::endl ;     return  l - r; } float  sub (float  l, float  r)   {    std ::cout  << "compute float "  << l << " - "  << r << " :"  << std ::endl ;     return  l - r; } PYBIND11_MODULE(compute_pybind_state, m) { 		m.doc() = "pybind11 compute plugin" ;   	py::class_<Binary>(m, "Binary" )         .def(py::init<>())         .def(py::init<const  std ::string &>())         .def("set" , py::overload_cast<const  std ::string &>(&Binary::set ), "set the binary's type." )         .def("set" , py::overload_cast<const  int >(&Binary::set ), "test overloaded function." )         .def("get_mutable" , py::overload_cast<>(&Binary::get ), "get the binary's type by mutable." )         .def("get_const" , py::overload_cast<>(&Binary::get , py::const_), "get the binary's type." )         .def("compute" , &Binary::compute, "compute the binary's result." )         .def_readwrite("type_" , &Binary::type_, "the attribute of binary." )         .def("__repr__" ,              [](const  Binary& a) { return  "<example.Binary type '"  + a.type_ + "'>" ; }); } 
 
注意,py::overload_cast 需 c++14 及其以上版本方可支持。
类函数重载在 c++11 的写法如下
1 2 3 4 5 6 7 8 9 10 11 12 13 PYBIND11_MODULE(compute_pybind_state, m) { 		m.doc() = "pybind11 compute plugin" ;   	py::class_<Binary>(m, "Binary" )         .def(py::init<>())         .def(py::init<const  std ::string &>())         .def("set" , (void (Binary::*)(const  std ::string &))&Binary::set , "set the binary's type." )         .def("set" , (void (Binary::*)(const  int ))&Binary::set , "test overloaded function." )         .def("get" , &Binary::get , "get the binary's type." )         .def("compute" , &Binary::compute, "compute the binary's result." )         .def_readwrite("type_" , &Binary::type_, "the attribute of binary." )         .def("__repr__" ,              [](const  Binary& a) { return  "<example.Binary type '"  + a.type_ + "'>" ; }); } 
 
Python测试代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 b1 = CXX.Binary() print(b1) b1.type_ = "div"  print(b1.get_mutable()) print(b1.get_const()) b2 = CXX.Binary("sub" ) print(b2.compute(11.0 , 2.0 )) b2.set("mul" ) print(b2.compute(11.0 , 2.0 )) 
 
其他用法 注册模块变量 C++示例源码:
1 2 3 4 5 6 7 8 9 10 11 #include  "pybind11/pybind11.h"  namespace  py = pybind11;PYBIND11_MODULE(compute_pybind_state, m) { 		m.doc() = "pybind11 compute plugin" ;   	m.attr("author" ) = "wzx1" ;     py::object content = py::cast("HelloWorld" );     m.attr("content" ) = content; } 
 
参考资料